2016/09/21

Recent entries from same category

  1. Go 言語プログラミングエッセンスという本を書きました。
  2. errors.Join が入った。
  3. unsafe.StringData、unsafe.String、unsafe.SliceData が入った。
  4. Re: Go言語で画像ファイルか確認してみる
  5. net/url に JoinPath が入った。

以前から c-archive は作れたけど DLL にするとシンボルが被ったりして上手く DLL が作れなかった。

Big Sky :: golang の Windows 版が buildmode=c-archive をサポートした。

だいぶ時間が掛かった様ですが、ようやく buildmode=c-archive が Windows でも使える様になりました。 cmd/go: -buildmode=c-archive should ...

http://mattn.kaoriya.net/software/lang/go/20160405114638.htm
cmd/go: -buildmode=c-shared should work on windows · Issue #11058 · golang/go · GitHub
https://github.com/golang/go/issues/11058#issuecomment-248330515

-Wl,--allow-multiple-definition を知らなかった。

package main

import "C"

func main() {
}

//export HelloWorld
func HelloWorld() {
    println("Hello golang!")
}

まずこの様なソースコードを c-archive にして libxxx.a を作る。 go build -buildmode=c-archive -o libxxx.a xxx.go

次に HelloWorld をエントリにする def ファイルを作る。

LIBRARY   helloworld
EXPORTS
   HelloWorld

そして def ファイルを指定して DLL を生成する。この時 -Wl,--allow-multiple-definition を指定すること。

gcc -m64 -shared -o xxx.dll xxx.def libxxx.a -Wl,--allow-multiple-definition -static -lstdc++ -lwinmm -lntdll -lWs2_32

後は呼び出し元を作って...

package main

import "syscall"

var (
    lib        = syscall.NewLazyDLL("xxx.dll")
    helloworld = lib.NewProc("HelloWorld")
)

func main() {
    helloworld.Call()
}
Golang で DLL!

C言語からも

#include <windows.h>

typedef void (*pfn)(void);

int
main(int argc, char* argv[]) {
    pfn fn;
    HMODULE h = LoadLibrary("xxx.dll");
    fn = (pfn) GetProcAddress(h, "HelloWorld");
    fn();
    return 0;
}
Golang で DLL!

Golang のランタイムが FreeLibrary される事を想定していないので Vim の libcall からは直では呼び出せないけど libcallex-vim を使って解放なしに呼び出せば実行可能。ただしハンドルは持ちっぱなしにしないとリークする。

let xxx = libcallex#load("xxx.dll")
call xxx.call("HelloWorld", [], "")
"call xxx.free()

やったー!これで勝つる!

Posted at by